Klasyfikacja obiektów o okrągłym kształcie

Projekt zaliczeniowy - Automatyczna Analiza Obrazu

Autor
Instytucja

Szymon Olędzki

Politechnika Lubelska

Cel projektu i charakterystyka zbioru danych

Celem niniejszego projektu jest stworzenie modelu konwolucyjnej sieci neuronowej, której zadaniem jest klasyfikacja 30 różnych rodzajów obiektów o kształcie okrągłym lub do niego zbliżonym.

Zbiór danych, który wykorzystałem do zrealizowania zadania to 30 Types of Balls Updated, dostępny na platformie Kaggle. Zawiera on 3895 zdjęć obiektów, podzielonych na następujące klasy:

  • 0 - Baseball - piłki baseballowe
  • 1 - Basketball - piłki do koszykówki
  • 2 - Beachballs - piłki plażowe
  • 3 - Billiard ball - bile bilardowe
  • 4 - Bowling ball - kule do kręgli
  • 5 - Brass - kule mosiężne
  • 6 - Buckeyballs - fulereny
  • 7 - Cannon ball - kule armatnie
  • 8 - Crochet ball - piłki szydełkowane
  • 9 - Cricket ball - piłki do krykieta
  • 10 - Crystal ball - kule kryształowe
  • 11 - Eyeballs - gałki oczne
  • 12 - Football - piłki do futbolu amerykańskiego
  • 13 - Golf ball - piłki golfowe
  • 14 - Marble - kulki szklane
  • 15 - Meat ball - klopsiki
  • 16 - Medicine ball - piłki lekarskie
  • 17 - Paint balls - kulki do paintballa
  • 18 - Pokeman balls - Pokeballe
  • 19 - Puffballs - purchawki
  • 20 - Rubberband ball - piłki z gumek
  • 21 - Screwballs - ludzkie twarze (ang. świrusy)
  • 22 - Sepak takraw ball - piłki do sepak takraw
  • 23 - Soccer ball - piłki nożne
  • 24 - Tennis ball - piłki tenisowe
  • 25 - Tether ball - piłki do tetherballa
  • 26 - Volley ball - piłki do siatkówki
  • 27 - Water polo ball - piłki do wodnego polo
  • 28 - Wiffle ball - piłki do wiffle balla
  • 29 - Wrecking ball - kule wyburzeniowe

Oryginalny zbiór podzielony jest na 3 foldery, dla zbiorów treningowego, walidacyjnego i testowego w taki sposób, by dla każdej z klas w zbiorze walidacyjnym i testowym było po 5 zdjęć. Nie jest to proporcja jaką chciałem zastosować przy uczeniu i ewaluacji modeli, zatem przed przystąpieniem do uczenia zmieniłem proporcję plików w poszczególnych zbiorach (70%/15%/15%).

Wykorzystane architektury sieci neuronowych

W ramach projektu uczenie przeprowadzę na 4 zaproponowanych przeze mnie autorskich architekturach oraz na 2 wcześniej nauczonych dostępnych w pakiecie Keras. Oprócz klasycznej metryki dokładności wyniki poszczególnych modeli porównam również dla metryk klasy top_n, dla 3 i 10 klas z największym prawdopodobieństwem.

Architektury własne

Pierwsza sieć

Jako pierwszą, “benchmarkową” architekturę wybrałem prostą sieć składającą się z trzech warstw kowolucyjnych (odpowiednio \(32\), \(64\) i \(128\) filtrów) połączonych warstwami max-pooling (rozmiar okna: \(2\times2\)) oraz jednej warstwy gęstej (\(512\) neuronów) poprzedzającej warstwę wyjściową.

  • Dla wszystkich warstw z wyjątkiem wyjściowej zastosowałem funkcję aktywacji ReLU, w przypadku tej ostatniej funkcją aktywacji jest Softmax.

  • Wybrana przeze mnie funkcja optymalizacji to Adam.

  • Sieć jest trenowana przez \(80\) epok z \(85\) krokami w każdej z nich.

Pokaż kod
model <- keras_model_sequential() %>%
  layer_conv_2d(filters = 32, kernel_size = c(3, 3), activation = 'relu', input_shape = c(224, 224, 3)) %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  
  layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = 'relu') %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  
  layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = 'relu') %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  
  layer_flatten() %>%
  layer_dense(units = 512, activation = 'relu') %>%
  layer_dense(units = 30, activation = 'softmax')
Model: "sequential"
________________________________________________________________________________
 Layer (type)                       Output Shape                    Param #     
================================================================================
 conv2d_2 (Conv2D)                  (None, 222, 222, 32)            896         
 max_pooling2d_2 (MaxPooling2D)     (None, 111, 111, 32)            0           
 conv2d_1 (Conv2D)                  (None, 109, 109, 64)            18496       
 max_pooling2d_1 (MaxPooling2D)     (None, 54, 54, 64)              0           
 conv2d (Conv2D)                    (None, 52, 52, 128)             73856       
 max_pooling2d (MaxPooling2D)       (None, 26, 26, 128)             0           
 flatten (Flatten)                  (None, 86528)                   0           
 dense_1 (Dense)                    (None, 512)                     44302848    
 dense (Dense)                      (None, 30)                      15390       
================================================================================
Total params: 44411486 (169.42 MB)
Trainable params: 44411486 (169.42 MB)
Non-trainable params: 0 (0.00 Byte)
________________________________________________________________________________

Wyniki uczenia pierwszej sieci

Na pierwszy rzut oka można zauważyć ogromne przeuczenie, a dokładność na zbiorze walidacyjnym po 80 epokach osiąga ledwie \(0.25\). Wyniki dla metryk top3 i top10 również nie są satysfakcjonujące.

Druga sieć

Moja druga propozycja architektury opiera się na poprawieniu pierwszej propozycji przez wzgląd na jej duże przeuczenie. Tym razem po każdej warstwie konwolucyjnej zastosowałem batch normalization, żeby poprawić stabilność treningu, dodałem również warstwy dropout o wartościach współczynnika \(0.25\) po warstwach konwolucyjnych i \(0.5\) przed warstwą wyjściową oraz regularyzację L2 dla warstwy gęstej, żeby zmniejszyć przeuczenie.

Zmian dokonałem również w ramach optymalizatora - nadal jest to Adam, jednak tym razem z ustalonym współczynnikiem uczenia \(0.001\).

Do procesu uczenia dodałem również dwa callbacki:

  • Reduce Learning Rate on Plateau - dynamicznie zmniejsza współczynnik uczenia, gdy wynik modelu na zbiorze walidacyjnym przestaje się poprawiać po 5 epokach,

  • Early Stopping - pomaga zapobiegać przeuczeniu zatrzymując trening, gdy wynik modelu na zbiorze walidacyjnym przestaje się poprawiać po 10 epokach.

Pokaż kod
model <- keras_model_sequential() %>%
  layer_conv_2d(filters = 32, kernel_size = c(3, 3), activation = 'relu', input_shape = c(224, 224, 3)) %>%
  layer_batch_normalization() %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_dropout(rate = 0.25) %>%
  
  layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = 'relu') %>%
  layer_batch_normalization() %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_dropout(rate = 0.25) %>%
  
  layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = 'relu') %>%
  layer_batch_normalization() %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_dropout(rate = 0.25) %>%
  
  layer_flatten() %>%
  layer_dense(units = 512, activation = 'relu', kernel_regularizer = regularizer_l2(0.001)) %>%
  layer_dropout(rate = 0.5) %>%
  layer_dense(units = 30, activation = 'softmax')
Model: "sequential_1"
________________________________________________________________________________
 Layer (type)                  Output Shape               Param #    Trainable  
================================================================================
 conv2d_5 (Conv2D)             (None, 222, 222, 32)       896        Y          
 batch_normalization_2 (Batch  (None, 222, 222, 32)       128        Y          
 Normalization)                                                                 
 max_pooling2d_5 (MaxPooling2  (None, 111, 111, 32)       0          Y          
 D)                                                                             
 dropout_3 (Dropout)           (None, 111, 111, 32)       0          Y          
 conv2d_4 (Conv2D)             (None, 109, 109, 64)       18496      Y          
 batch_normalization_1 (Batch  (None, 109, 109, 64)       256        Y          
 Normalization)                                                                 
 max_pooling2d_4 (MaxPooling2  (None, 54, 54, 64)         0          Y          
 D)                                                                             
 dropout_2 (Dropout)           (None, 54, 54, 64)         0          Y          
 conv2d_3 (Conv2D)             (None, 52, 52, 128)        73856      Y          
 batch_normalization (BatchNo  (None, 52, 52, 128)        512        Y          
 rmalization)                                                                   
 max_pooling2d_3 (MaxPooling2  (None, 26, 26, 128)        0          Y          
 D)                                                                             
 dropout_1 (Dropout)           (None, 26, 26, 128)        0          Y          
 flatten_1 (Flatten)           (None, 86528)              0          Y          
 dense_3 (Dense)               (None, 512)                44302848   Y          
 dropout (Dropout)             (None, 512)                0          Y          
 dense_2 (Dense)               (None, 30)                 15390      Y          
================================================================================
Total params: 44412382 (169.42 MB)
Trainable params: 44411934 (169.42 MB)
Non-trainable params: 448 (1.75 KB)
________________________________________________________________________________

Wyniki uczenia drugiej sieci

Zauważyć można zdecydowaną poprawę, jak widać zastosowane kroki przyniosły oczekiwany efekt, chociaż od pewnego momentu nadal można zaobserwować przeuczenie. Dokładność na zbiorze walidacyjnym wyniosła tym razem około \(0.5\), co jest zauważalnie lepszym, aczkolwiek nadal niesatysfakcjonującym wynikiem. Zastosowane callbacki również zadziałały skutecznie - sieć zakończyła uczenie wcześniej, gdy wynik na zbiorze walidacyjnym przestał się poprawiać, mimo założonych 80 epok uczenia. Metryka top3 wskazuje \(0.75\) dokładności, natomiast top10 ponad \(0.9\).

Trzecia sieć

Architektura trzeciej sieci różni się od poprzedniej w trzech aspektach. Zamiast jednej warstwy gęstej zastosowałem dwie, ale z mniejszą liczbą neuronów. Drugą zmianą jest zmniejszona wartość współczynnika we wszystkich warstwach dropout, tym razem dla wszystkich jest to \(0.2\).

Ostatnią zmianą jest zmniejszenie początkowego współczynnika uczenia przy optymalizatorze Adam na \(0.0001\). Stosuję nadal te same callbacki i uczenie przez 80 epok.

Pokaż kod
model <- keras_model_sequential() %>%
    layer_conv_2d(filters = 32, kernel_size = c(3, 3), activation = 'relu', input_shape = c(224, 224, 3)) %>%
    layer_max_pooling_2d(pool_size = c(2, 2)) %>%
    layer_batch_normalization() %>%
    layer_dropout(rate = 0.2) %>%
  
    layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = 'relu') %>%
    layer_max_pooling_2d(pool_size = c(2, 2)) %>%
    layer_batch_normalization() %>%
    layer_dropout(rate = 0.2) %>%
  
    layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = 'relu') %>%
    layer_max_pooling_2d(pool_size = c(2, 2)) %>%
    layer_batch_normalization() %>%
    layer_dropout(rate = 0.2) %>%
  
    layer_flatten() %>%
    layer_dense(units = 128, activation = 'relu', kernel_regularizer = regularizer_l2(0.001)) %>%
    layer_dropout(rate = 0.2) %>%
    layer_dense(units = 64, activation = 'relu', kernel_regularizer = regularizer_l2(0.001)) %>%
    layer_dropout(rate = 0.2) %>%
    layer_dense(units = 30, activation = 'softmax')
Model: "sequential_2"
________________________________________________________________________________
 Layer (type)                  Output Shape               Param #    Trainable  
================================================================================
 conv2d_8 (Conv2D)             (None, 222, 222, 32)       896        Y          
 max_pooling2d_8 (MaxPooling2  (None, 111, 111, 32)       0          Y          
 D)                                                                             
 batch_normalization_5 (Batch  (None, 111, 111, 32)       128        Y          
 Normalization)                                                                 
 dropout_8 (Dropout)           (None, 111, 111, 32)       0          Y          
 conv2d_7 (Conv2D)             (None, 109, 109, 64)       18496      Y          
 max_pooling2d_7 (MaxPooling2  (None, 54, 54, 64)         0          Y          
 D)                                                                             
 batch_normalization_4 (Batch  (None, 54, 54, 64)         256        Y          
 Normalization)                                                                 
 dropout_7 (Dropout)           (None, 54, 54, 64)         0          Y          
 conv2d_6 (Conv2D)             (None, 52, 52, 128)        73856      Y          
 max_pooling2d_6 (MaxPooling2  (None, 26, 26, 128)        0          Y          
 D)                                                                             
 batch_normalization_3 (Batch  (None, 26, 26, 128)        512        Y          
 Normalization)                                                                 
 dropout_6 (Dropout)           (None, 26, 26, 128)        0          Y          
 flatten_2 (Flatten)           (None, 86528)              0          Y          
 dense_6 (Dense)               (None, 128)                11075712   Y          
 dropout_5 (Dropout)           (None, 128)                0          Y          
 dense_5 (Dense)               (None, 64)                 8256       Y          
 dropout_4 (Dropout)           (None, 64)                 0          Y          
 dense_4 (Dense)               (None, 30)                 1950       Y          
================================================================================
Total params: 11180062 (42.65 MB)
Trainable params: 11179614 (42.65 MB)
Non-trainable params: 448 (1.75 KB)
________________________________________________________________________________

Wyniki uczenia trzeciej sieci

Widać, że zmiany przyniosły oczekiwany efekt, jest to delikatna, ale zauważalna zmiana - udało się przekroczyć próg \(0.6\) dokładności na zbiorze walidacyjnym i zmniejszyć przeuczenie. Wyniki dla metryk top3 i top10 nieznacząco się poprawiły.

Czwarta sieć

Czwarta i ostatnia propozycja mojej własnej architektury zawiera dodatkową warstwę konwolucyjną przed warstwami gęstymi. Zdecydowałem się na ten krok widząc, że w poprzedniej iteracji poprawę przyniosło dodanie warstwy gęstej. Dodana warstwa konwolucyjna zawiera (podobnie jak wcześniejsze warstwy) dwa razy więcej filtrów niż poprzednia. Postanowiłem zmienić również wartości współczynników w warstwach dropout, tym razem są wyższe i zwiększają się co dwie warstwy konwolucyjne.

Podobnie jak w przy poprzedniej architekturze nie zmieniałem optymalizatora, callbacków, ani czasu uczenia.

Pokaż kod
model <- keras_model_sequential() %>%
  layer_conv_2d(filters = 32, kernel_size = c(3, 3), activation = 'relu', input_shape = c(224, 224, 3)) %>%
  layer_batch_normalization() %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_dropout(rate = 0.3) %>%
  
  layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = 'relu') %>%
  layer_batch_normalization() %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_dropout(rate = 0.3) %>%
  
  layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = 'relu') %>%
  layer_batch_normalization() %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_dropout(rate = 0.4) %>%
  
  layer_conv_2d(filters = 256, kernel_size = c(3, 3), activation = 'relu') %>%
  layer_batch_normalization() %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_dropout(rate = 0.4) %>%
  
  layer_flatten() %>%
  layer_dense(units = 128, activation = 'relu', kernel_regularizer = regularizer_l2(0.001)) %>%
  layer_batch_normalization() %>%
  layer_dropout(rate = 0.5) %>%

  layer_dense(units = 64, activation = 'relu', kernel_regularizer = regularizer_l2(0.001)) %>%
  layer_batch_normalization() %>%
  layer_dropout(rate = 0.5) %>%
  layer_dense(units = 30, activation = 'softmax')
Model: "sequential_3"
________________________________________________________________________________
 Layer (type)                  Output Shape               Param #    Trainable  
================================================================================
 conv2d_12 (Conv2D)            (None, 222, 222, 32)       896        Y          
 batch_normalization_11 (Batc  (None, 222, 222, 32)       128        Y          
 hNormalization)                                                                
 max_pooling2d_12 (MaxPooling  (None, 111, 111, 32)       0          Y          
 2D)                                                                            
 dropout_14 (Dropout)          (None, 111, 111, 32)       0          Y          
 conv2d_11 (Conv2D)            (None, 109, 109, 64)       18496      Y          
 batch_normalization_10 (Batc  (None, 109, 109, 64)       256        Y          
 hNormalization)                                                                
 max_pooling2d_11 (MaxPooling  (None, 54, 54, 64)         0          Y          
 2D)                                                                            
 dropout_13 (Dropout)          (None, 54, 54, 64)         0          Y          
 conv2d_10 (Conv2D)            (None, 52, 52, 128)        73856      Y          
 batch_normalization_9 (Batch  (None, 52, 52, 128)        512        Y          
 Normalization)                                                                 
 max_pooling2d_10 (MaxPooling  (None, 26, 26, 128)        0          Y          
 2D)                                                                            
 dropout_12 (Dropout)          (None, 26, 26, 128)        0          Y          
 conv2d_9 (Conv2D)             (None, 24, 24, 256)        295168     Y          
 batch_normalization_8 (Batch  (None, 24, 24, 256)        1024       Y          
 Normalization)                                                                 
 max_pooling2d_9 (MaxPooling2  (None, 12, 12, 256)        0          Y          
 D)                                                                             
 dropout_11 (Dropout)          (None, 12, 12, 256)        0          Y          
 flatten_3 (Flatten)           (None, 36864)              0          Y          
 dense_9 (Dense)               (None, 128)                4718720    Y          
 batch_normalization_7 (Batch  (None, 128)                512        Y          
 Normalization)                                                                 
 dropout_10 (Dropout)          (None, 128)                0          Y          
 dense_8 (Dense)               (None, 64)                 8256       Y          
 batch_normalization_6 (Batch  (None, 64)                 256        Y          
 Normalization)                                                                 
 dropout_9 (Dropout)           (None, 64)                 0          Y          
 dense_7 (Dense)               (None, 30)                 1950       Y          
================================================================================
Total params: 5120030 (19.53 MB)
Trainable params: 5118686 (19.53 MB)
Non-trainable params: 1344 (5.25 KB)
________________________________________________________________________________

Wyniki uczenia czwartej sieci

Po raz kolejny zauważyć można wzrost dokładności na zbiorze walidacyjnym, tym razem jest on bliski \(0.75\), jednak zwiększyło się również przeuczenie, względem poprzedniej architektury. Metryki top3 i top10 osiągnęły zadowalające wyniki - ok. \(0.9\) i \(0.95\).

Transfer Learning

Pakiet Keras udostępnia wstępnie wytrenowane modele, w tym DenseNet201 i VGG19, które są dostępne dla użytkowników do wykorzystania np. w ramach transfer learningu. Poniżej przedstawiam wyniki uczenia tych dwóch wybranych modeli na moim zbiorze danych. W obu przypadkach do gotowej architektury dodałem dwie warstwy gęste razem z warstwami batch normalization i dropout, podobnie jak w ostatniej autorskiej architekturze. Zastosowałem również ten sam optymalizator, callbacki oraz czas uczenia.

Densenet201

Pokaż kod
base_model <- application_densenet201(weights = "imagenet", include_top = FALSE, input_shape = c(224, 224, 3))

freeze_weights(base_model)

model <- keras_model_sequential() %>%
  base_model %>%

  layer_global_average_pooling_2d() %>%
  layer_dense(units = 128, activation = 'relu', kernel_regularizer = regularizer_l2(0.001)) %>%
  layer_batch_normalization() %>%
  layer_dropout(rate = 0.5) %>%

  layer_dense(units = 64, activation = 'relu', kernel_regularizer = regularizer_l2(0.001)) %>%
  layer_batch_normalization() %>%
  layer_dropout(rate = 0.5) %>%
  layer_dense(units = 30, activation = 'softmax')
Model: "sequential_4"
________________________________________________________________________________
 Layer (type)                  Output Shape               Param #    Trainable  
================================================================================
 densenet201 (Functional)      (None, 7, 7, 1920)         18321984   N          
 global_average_pooling2d (Gl  (None, 1920)               0          Y          
 obalAveragePooling2D)                                                          
 dense_12 (Dense)              (None, 128)                245888     Y          
 batch_normalization_13 (Batc  (None, 128)                512        Y          
 hNormalization)                                                                
 dropout_16 (Dropout)          (None, 128)                0          Y          
 dense_11 (Dense)              (None, 64)                 8256       Y          
 batch_normalization_12 (Batc  (None, 64)                 256        Y          
 hNormalization)                                                                
 dropout_15 (Dropout)          (None, 64)                 0          Y          
 dense_10 (Dense)              (None, 30)                 1950       Y          
================================================================================
Total params: 18578846 (70.87 MB)
Trainable params: 256478 (1001.87 KB)
Non-trainable params: 18322368 (69.89 MB)
________________________________________________________________________________

Wyniki uczenia sieci DenseNet201

Jak widać model ten osiągnął dokładność podobną do czwartej proponowanej przeze mnie architektury, mając jednak zauważalnie niższe przeuczenie. Dla metryki top3 wynik również jest podobny, wartość metryki top10 poprawiła się.

VGG19

Pokaż kod
base_model <- application_vgg19(weights = "imagenet", include_top = FALSE, input_shape = c(224, 224, 3))

freeze_weights(base_model)

model <- keras_model_sequential() %>%
  base_model %>%

  layer_global_average_pooling_2d() %>%
  layer_dense(units = 128, activation = 'relu', kernel_regularizer = regularizer_l2(0.001)) %>%
  layer_batch_normalization() %>%
  layer_dropout(rate = 0.5) %>%

  layer_dense(units = 64, activation = 'relu', kernel_regularizer = regularizer_l2(0.001)) %>%
  layer_batch_normalization() %>%
  layer_dropout(rate = 0.5) %>%
  layer_dense(units = 30, activation = 'softmax')
Model: "sequential_5"
________________________________________________________________________________
 Layer (type)                  Output Shape               Param #    Trainable  
================================================================================
 vgg19 (Functional)            (None, 7, 7, 512)          20024384   N          
 global_average_pooling2d_1 (  (None, 512)                0          Y          
 GlobalAveragePooling2D)                                                        
 dense_15 (Dense)              (None, 128)                65664      Y          
 batch_normalization_15 (Batc  (None, 128)                512        Y          
 hNormalization)                                                                
 dropout_18 (Dropout)          (None, 128)                0          Y          
 dense_14 (Dense)              (None, 64)                 8256       Y          
 batch_normalization_14 (Batc  (None, 64)                 256        Y          
 hNormalization)                                                                
 dropout_17 (Dropout)          (None, 64)                 0          Y          
 dense_13 (Dense)              (None, 30)                 1950       Y          
================================================================================
Total params: 20101022 (76.68 MB)
Trainable params: 76254 (297.87 KB)
Non-trainable params: 20024768 (76.39 MB)
________________________________________________________________________________

Wyniki uczenia sieci VGG19

Model sieci VGG19 osiągnął najlepszy wynik spośród wszystkich 6 modeli, deklasując konkurencję wynikiem ponad \(0.95\) dokładności na zbiorze walidacyjnym. Wartości metryki dokładności dla zbioru treningowego i walidacyjnego niemal się pokrywają, zatem efekt przeuczenia dla tego modelu jest najmniejszy. Metryki top3 i top10 osiągnęły wyniki zbliżone do \(1.0\).

Ewaluacja modeli

Ewaluację przeprowadzam dla dwóch modeli, które osiągnęły najlepsze wyniki na zbiorze walidacyjnym. Porównam zatem wyniki dla czwartej proponowanej przeze mnie architektury i sieci VGG19. Dla obu modeli przedstawię macierz konfuzji oraz przykładowe, błędnie sklasyfikowane obrazy ze zbioru testowego.

Czwarta sieć własna

Macierz konfuzji czwartej sieci własnej

Przykładowe 9 błędnych klasyfikacji czwartej sieci własnej

Na zbiorze testowym model osiągnął \(71.62\%\) dokładności.

Najczęstsza błędna predykcja: bile bilardowe jako szklane kulki

Najgorzej przewidywana klasa: kulki do paintballa

VGG19

Macierz konfuzji dla sieci VGG19

Przykładowe 9 błędnych klasyfikacji sieci VGG19

Na zbiorze testowym model osiągnął \(93.66\%\) dokładności.

Najczęstsza błędna predykcja: pokeballe jako kule do kręgli, piłki do wodnego polo jako piłki do siatkówki

Najgorzej przewidywana klasa: kulki do paintballa

Podsumowanie

Model sieci VGG19 okazał się być dużo dokładniejszy od proponowanej przeze mnie architektury, należy jednak pamiętać, że są to modele o zupełnie różnej złożoności (\(20.101.022\) parametrów vs. \(5.120.030\) parametrów). W przypadku problemu z aż 30 klasami, których obiekty mają wiele cech wspólnych uważam osiągnięte przeze mnie wyniki za dobre.